package com.gitee.wsgalaxy.gnodroid.connect;

import android.util.Log;

import com.gitee.wsgalaxy.gnodroid.GndGlobal;
import com.gitee.wsgalaxy.gnodroid.module.GndModule;

import org.json.JSONObject;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;

/**
 * Created by wsgalaxy on 3/17/18.
 */

/**
 * 管理会话
 */
public class GndSession {
    SocketChannel socket_channel = null;
    GndModule module = null;
    GndConnect connect = null;
    int buffer_size = GndGlobal.BYTE_BUFFER_SIZE;
    ByteBuffer byte_buffer = ByteBuffer.allocate(GndGlobal.BYTE_BUFFER_SIZE);
    ByteBuffer byte_buffer_w = ByteBuffer.allocate(GndGlobal.BYTE_BUFFER_SIZE);

    public GndSession(SocketChannel gndChannel, GndConnect gndConnect)
    {
        socket_channel = gndChannel;
        connect = gndConnect;
        connect.attachChannel(gndChannel, SelectionKey.OP_READ);
    }

    public boolean checkChannel(SocketChannel channel)
    {
        return socket_channel == channel;
    }

    /**
     * 挂在nio上的channel有东西时
     * @param selectionKey
     * @return
     * @throws IOException
     */
    public boolean selectionKeyGot(SelectionKey selectionKey) throws IOException
    {
        Log.d("gnd", "session get key");
        if (selectionKey.isReadable()) {
            //读取数据
            byte_buffer.clear();
            int readBytes = ((SocketChannel) selectionKey.channel()).read(byte_buffer);
            //数据读取失败
            if (readBytes == 0 || readBytes == -1) {
                selectionKey.cancel();
                connect.session_list.remove(this);
                return false;
            }

            byte_buffer.flip();
            byte[] bytes = new byte[byte_buffer.remaining()];
            byte_buffer.get(bytes);

            if (module == null) {
                //未绑定有模块
                if (!matchModule(bytes)) {
                    //模块绑定失败
                    selectionKey.cancel();
                    connect.session_list.remove(this);
                    //connect = null;
                    return false;
                } else {
                    //在模块线程运行模块
                    ModulePost modulePost = new ModulePost();
                    modulePost.bytes = bytes;
                    connect.module_handle.post(modulePost);
                    return true;
                }
            } else {
                //在模块线程运行模块
                ModulePost modulePost = new ModulePost();
                modulePost.bytes = bytes;
                connect.module_handle.post(modulePost);
                return true;
            }
        }

        return false;
    }

    //根据请求的模块名匹配模块
    public boolean matchModule(byte[] bytes)
    {

        GndMessage gndMessage = GndMessage.generateMessage(bytes, bytes.length);
        if (gndMessage == null || gndMessage.message_data_list.size() == 0) {
            return false;
        }

        try {
            String strJson = new String(gndMessage.message_data_list.get(0).data, "UTF-8");
            JSONObject jsonObject = new JSONObject(strJson);
            String moduleId = jsonObject.getString("name");
            GndModule gndModule = GndGlobal.matchModule(moduleId);
            if (gndModule == null) {
                return false;
            } else {
                module = gndModule;
                module.session = this;
            }
        } catch (Exception e) {
            Log.d("gnd", e.getMessage() + "");
            e.printStackTrace();
            return false;

        }



        return true;
    }

    //发送数据
    //可在其他线程运行（？）
    public boolean dataSend(byte[] bytes)
    {
        //连接已关闭
        if (socket_channel == null || !socket_channel.isOpen()) {
            connect.session_list.remove(this);
            module.session = null;
            module = null;
            connect = null;
            return false;
        }

        while (bytes.length > buffer_size) {
            buffer_size *= 2;
        }

        byte_buffer_w = ByteBuffer.allocate(buffer_size);

        //发送数据
        byte_buffer_w.clear();
        byte_buffer_w.put(bytes);
        byte_buffer_w.flip();
        try {
            socket_channel.write(byte_buffer_w);
        } catch (Exception e) {
            Log.d("gnd", e.getMessage());
            return false;
        }
        return true;
    }


    /**
     * 将处理过程交给模块线程
     */
    class ModulePost implements Runnable
    {
        public byte[] bytes = null;

        public void run()
        {
            //运行模块的数据处理函数
            module.dataRequest(bytes);
        }
    }
}
